'''
    Example external client for BlueSky.

    When you run this file, make sure python knows where to find BlueSky:

    PYTHONPATH=/path/to/your/bluesky python textclient.py
'''
import sys
import os
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QComboBox
from PySide2 import QtWidgets
from bluesky.network import Client
import random
from time import sleep
import datetime
#移植sub部分（苏雨）
import zmq
import time
import numpy as np
# Local imports
import bluesky as bs
from bluesky import stack
from bluesky.tools import areafilter
from bluesky.core.walltime import Timer


# The echo textbox, command line, and bluesky network client as globals
echobox = None
cmdline = None
bsclient = None

#移植sub部分（苏雨）
context = zmq.Context()
#请注意，这里为了接收经纬度信息，打开了两个socket（苏雨）
socket = context.socket(zmq.SUB)
socket.connect("tcp://localhost:5555")
#接收所有消息并用utf-8转码（苏雨）
socket.setsockopt(zmq.SUBSCRIBE,''.encode('utf-8'))
#定义初始化开关，如果开关置于1，则定义数组并初始化，这是为了防止先创建飞机再启动节点，导致数组未定义的错误！（苏雨） 
global init
init = 1 
#定义数据选择开关，如果为0则开关处于中间，如果为1则数据进入lat，如果为2则数据进入lon，如果为3则进入alt，如果为4则进入tas，如果为5则进入trk（苏雨）
global latlonalt
latlonalt = 0
#定义位置信息存储数组（苏雨）
global lat_save
global lon_save
global alt_save
global tas_save
global trk_save
lat_save = []
lon_save = []
alt_save = []
tas_save = []
trk_save = []
#定义需要显示位置信息的飞机序号（苏雨）
global aircraft_order
aircraft_order = 0

class TextClient(Client):
    '''
        Subclassed Client with a timer to periodically check for incoming data,
        an overridden event function to handle data, and a stack function to
        send stack commands to BlueSky.
    '''
    def __init__(self):
        super().__init__()
        self.timer = QTimer()
        self.timer.timeout.connect(self.receive)
        self.timer.start(20)

    def event(self, name, data, sender_id):
        ''' Overridden event function to handle incoming ECHO commands. '''
        if name == b'ECHO' and echobox is not None:
            echobox.echo(**data)

    def stack(self, text):
        ''' Stack function to send stack commands to BlueSky. '''
        self.send_event(b'STACKCMD', text)


class Echobox(QTextEdit):
    ''' Text box to show echoed text coming from BlueSky. '''
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMaximumHeight(50)
        self.setReadOnly(True)
        self.setFocusPolicy(Qt.NoFocus)

    def echo(self, text, flags=None):
        ''' Add text to this echo box. '''
        self.append(text)
        self.verticalScrollBar().setValue(self.verticalScrollBar().maximum())


class Cmdline(QTextEdit):
    ''' Wrapper class for the command line. '''
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMaximumHeight(50)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

    def keyPressEvent(self, event):
        ''' Handle Enter keypress to send a command to BlueSky. '''
        if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
            if bsclient is not None:
                bsclient.stack(self.toPlainText())
                echobox.echo(self.toPlainText())
            self.setText('')
        else:
            super().keyPressEvent(event)

#这个是下拉框窗口，暂时不用它了（苏雨）                                   
class ComboxDemo(QComboBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 单个添加条目（苏雨）
        
        ac_number = len(lat_save)
        print(ac_number)
        
        
        
        self.addItem('aircraft_1')
        self.addItem('aircraft_2')
        self.addItem('aircraft_3')
        # 多个添加条目（苏雨）
        self.addItems(['aircraft_4', 'aircraft_5', 'aircraft_6'])

        ''' 信号（苏雨）
        self.cb.currentIndexChanged[str].connect(self.print_value) # 条目发生改变，发射信号，传递条目内容（苏雨）
        self.cb.currentIndexChanged[int].connect(self.print_value)  # 条目发生改变，发射信号，传递条目索引（苏雨）
        self.cb.highlighted[str].connect(self.print_value)  # 在下拉列表中，鼠标移动到某个条目时发出信号，传递条目内容（苏雨）
        self.cb.highlighted[int].connect(self.print_value)  # 在下拉列表中，鼠标移动到某个条目时发出信号，传递条目索引（苏雨）
    def print_value(self, i):
        print(i)
        '''


#这个是箭头选择窗口（苏雨）
class QSpinBox(QSpinBox):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 单个添加条目（苏雨）
        self.setRange(0, 99)                                                     
        self.setSingleStep(1)                                                       
        self.setValue(0)                                                           
        self.valueChanged.connect(self.value_change_func)                           
 

 
    def value_change_func(self):
        global init
        global latlonalt 
        global lat_save
        global lon_save
        global alt_save
        global tas_save
        global trk_save
        global aircraft_order 
        aircraft_order = self.value()
        #print('value=%d' %aircraft_order)
        #print('value=%d' %self.value())
        #decimal_part = self.double_spinbox.value() - int(self.double_spinbox.value())       
        #self.double_spinbox.setValue(self.spinbox.value() + decimal_part)                   





#这是生成随机数的测试函数（苏雨）
class WorkThread(QThread):
  # 初始化线程（苏雨）
  def __int__(self):
    super(WorkThread, self).__init__()
  #线程运行函数（苏雨）
  def run(self):
      
      while True:
          #移植sub部分（苏雨）
          global init
          global latlonalt 
          global lat_save
          global lon_save
          global alt_save
          global tas_save
          global trk_save
          global aircraft_order         
          #如果第一次执行程序，则定义数组并初始化（苏雨）
          if init == 1:
              lat = []
              lon = []
              alt = []
              tas = []
              trk = []
              #初始化完成关闭初始化开关（苏雨）
              init = 0
          #response = socket.recv();
          response = socket.recv().decode('utf-8')
          #通过转义符区分每个采样周期所有飞机位置信息（苏雨）    
          if response == '"Position"':
              #print('Aircraft Position:')
              #在这里数组获得了所有飞机的参数（苏雨）
              #print(lat)
              #print(lon)
              lat_save = lat
              lon_save = lon
              alt_save = alt
              tas_save = tas
              trk_save = trk
              #edita1.setText(str(lat[0]))
              #edita2.setText(str(lon[0]))
              #edita1.setText('error!')
              #edita2.setText('error!')              
               
              #初始化数组，用来存储采样周期内所有飞机位置信息（苏雨）
              lat = []
              lon = []
              alt = []
              tas = []
              trk = []              
              latlonalt = 0    
          else:
              if response == '"Lat"':
                  latlonalt = 1
              elif response == '"Lon"':    
                  latlonalt = 2
              elif response == '"Alt"':    
                  latlonalt = 3 
              elif response == '"Tas"':    
                  latlonalt = 4
              elif response == '"Trk"':    
                  latlonalt = 5                                                     
              else:                     
                  if latlonalt == 1:
                      #将字符串类型转换为浮点数（苏雨）
                      transfer = float(response)   
                      #向数组末尾插信息（苏雨）
                      lat.append(transfer)
                      latlonalt = 0            
                  if latlonalt == 2:
                      #将字符串类型转换为浮点数（苏雨）
                      transfer = float(response)   
                      #向数组末尾插信息（苏雨）
                      lon.append(transfer)
                      latlonalt = 0
                  if latlonalt == 3:
                      #将字符串类型转换为浮点数（苏雨）
                      transfer = float(response)   
                      #向数组末尾插信息（苏雨）
                      alt.append(transfer)
                      latlonalt = 0
                  if latlonalt == 4:
                      #将字符串类型转换为浮点数（苏雨）
                      transfer = float(response)   
                      #向数组末尾插信息（苏雨）
                      tas.append(transfer)
                      latlonalt = 0
                  if latlonalt == 5:
                      #将字符串类型转换为浮点数（苏雨）
                      transfer = float(response)   
                      #向数组末尾插信息（苏雨）
                      trk.append(transfer)
                      latlonalt = 0                                            
          #print('value=%d' %aircraft_order)
          #print(lat_save)
          #print(lon_save)              
          #刷新率（苏雨）
          #sleep(0.1)
          #这里通过判断来决定显示框显示哪台飞机的数据（苏雨）
          size = len(lat_save)
          if aircraft_order == 0:
              edita1.setText('Please select an aircraft!')
              edita2.setText('Please select an aircraft!')
              edita3.setText('Please select an aircraft!')
              edita4.setText('Please select an aircraft!')
              edita5.setText('Please select an aircraft!')                             
          elif aircraft_order <= size:
              num =  aircraft_order-1
              latnum = lat_save[num]
              lonnum = lon_save[num]
              altnum = alt_save[num]
              tasnum = tas_save[num]
              trknum = trk_save[num]
              edita1.setText(str(latnum))
              edita2.setText(str(lonnum))
              edita3.setText(str(altnum))
              edita4.setText(str(tasnum))
              edita5.setText(str(trknum))
          else:
              edita1.setText('Error! Please select an correct aircraft!')
              edita2.setText('Error! Please select an correct aircraft!') 
              edita3.setText('Error! Please select an correct aircraft!')
              edita4.setText('Error! Please select an correct aircraft!')
              edita5.setText('Error! Please select an correct aircraft!')                                         


#定义打开FlightGear的函数（苏雨）
def FG_open():
    os.system("gnome-terminal -t \"Open FlightGear!\" -x bash -c \"cd /usr/games; fgfs --generic=socket,out,5,127.0.0.1,6789,udp,suyu_inputoutput --aircraft=mibs --httpd=5400 --generic=socket,in,5,127.0.0.1,1917,udp,zmq_test_control --generic=socket,in,5,127.0.0.1,4500,udp,zmq_test_position --ai-scenario=suyu_demo; exec bash;\"")
        
#定义连接FlightGear的函数（苏雨）
def FG_connect():
    os.system("gnome-terminal -t \"Connect to FlightGear!\" -x bash -c \"cd /home/suyu/suyu/FlightGear_connector/input; ./zmq_test_control; exec bash;\"")

#定义GPS校准的函数（苏雨）
def FG_GPS_calibration():
    os.system("gnome-terminal -t \"FlightGear GPS calibration!\" -x bash -c \"cd /home/suyu/suyu/FlightGear_connector/input; ./zmq_test_position; exit; exec bash;\"")

#定义打开BlueSky的函数（苏雨）
def BS_open():
    #注意，当打开了BlueSky后，程序才能和BlueSky建立连接（连接指示符设置为1），否则将黑屏！（苏雨） 
    os.system("gnome-terminal -t \"Open BlueSky!\" -x bash -c \"cd /home/suyu/bluesky-master; python3 BlueSky.py; exec bash;\"")    

#定义在FG打开前创建AI飞机的xml配置文件的函数（苏雨）
def FG_AI_create():
    os.system("gnome-terminal -t \"FlightGear AI create!\" -x bash -c \"cd /home/suyu/suyu/FlightGear_connector/protocol; echo \"ubuntu\" | sudo -S python3 xml_scenario.py; exit; exec bash;\"")

#定义在FG打开前创建protocol串口通讯xml配置文件的函数（苏雨）
def FG_protocol_create():
    os.system("gnome-terminal -t \"FlightGear xml position!\" -x bash -c \"cd /home/suyu/suyu/FlightGear_connector/protocol; echo \"ubuntu\" | sudo -S python3 xml_position.py; exit; exec bash;\"")
    os.system("gnome-terminal -t \"FlightGear xml control!\" -x bash -c \"cd /home/suyu/suyu/FlightGear_connector/protocol; echo \"ubuntu\" | sudo -S python3 xml_control.py; exit; exec bash;\"")
    os.system("gnome-terminal -t \"FlightGear xml output!\" -x bash -c \"cd /home/suyu/suyu/FlightGear_connector/protocol; echo \"ubuntu\" | sudo -S python3 xml_output.py; exit; exec bash;\"")


if __name__ == '__main__':
    # Construct the Qt main object
    app = QApplication([])

  
    workThread = WorkThread()
    workThread.start() 
    # Create a window with a stack text box and a command line (suyu)
    win = QWidget()
    #整个窗口大小（苏雨）
    win.setFixedSize(510,600)
    #btn_1.resize(100,200)
    #禁用窗口大小缩放（苏雨）
    win.setFixedSize(win.width(), win.height())    
    win.setWindowTitle('suyu')
    #定义飞机位置数值显示窗口（苏雨）
    edita1 = QLineEdit(win) 
    edita2 = QLineEdit(win)
    edita3 = QLineEdit(win)
    edita4 = QLineEdit(win)
    edita5 = QLineEdit(win)    
    echobox = Echobox(win)
    cmdline = Cmdline(win)
    label1 = QLabel(win)
    label2 = QLabel(win)
    label3 = QLabel(win)
    label4 = QLabel(win)
    label5 = QLabel(win)  
    label6 = QLabel(win)
    label7 = QLabel(win)
    label8 = QLabel(win)               
    bg_gender = QButtonGroup(win)
    bg_No = QButtonGroup(win)  
    spinbox = QSpinBox(win) 


    spinbox.setStyleSheet(
    #这里给按钮增加了背景图案和按键特效（苏雨）
    "QSpinBox:up-button{border-image: url(/home/suyu/suyu/picture/up_background.png)}"
    "QSpinBox:up-button:hover{border-image: url(/home/suyu/suyu/picture/up_hover.png)}"
    "QSpinBox:up-button:pressed{border-image: url(/home/suyu/suyu/picture/up_pressed.png)}"
    "QSpinBox:down-button{border-image: url(/home/suyu/suyu/picture/down_background.png)}"
    "QSpinBox:down-button:hover{border-image: url(/home/suyu/suyu/picture/down_hover.png)}"
    "QSpinBox:down-button:pressed{border-image: url(/home/suyu/suyu/picture/down_pressed.png)}"
    )


   
#Add a text description to the window (suyu)    
    label1.setText("BlueSky command line output:")
    label1.setAutoFillBackground(True) 
    palette = QPalette()        
    #palette.setColor(QPalette.Window,Qt.yellow)  
    label1.setPalette(palette) 
    label1.setAlignment( Qt.AlignLeft)
    #这里给文字说明增加特效（苏雨）
    label1.setStyleSheet(
    "QLabel:hover{color:red}"
    )
    
     
    label2.setText("BlueSky command line intput:")
    label2.setAutoFillBackground(True) 
    palette = QPalette()        
    #palette.setColor(QPalette.Window,Qt.yellow)  
    label2.setPalette(palette) 
    label2.setAlignment( Qt.AlignLeft)
    #这里给文字说明增加特效（苏雨）
    label2.setStyleSheet(
    "QLabel:hover{color:red}"
    )    
    
    label3.setText("BlueSky aircraft selsection:")
    label3.setAutoFillBackground(True) 
    palette = QPalette()        
    #palette.setColor(QPalette.Window,Qt.yellow)  
    label3.setPalette(palette) 
    label3.setAlignment( Qt.AlignLeft)
    #这里给文字说明增加特效（苏雨）
    label3.setStyleSheet(
    "QLabel:hover{color:orange}"
    ) 
        
    label4.setText("Latitude:")
    label4.setAutoFillBackground(True) 
    palette = QPalette()        
    #palette.setColor(QPalette.Window,Qt.green)  
    label4.setPalette(palette) 
    label4.setAlignment( Qt.AlignLeft)
    #这里给文字说明增加特效（苏雨）
    label4.setStyleSheet(
    "QLabel:hover{color:green}"
    ) 
        
    label5.setText("Longitude:")
    label5.setAutoFillBackground(True) 
    palette = QPalette()        
    #palette.setColor(QPalette.Window,Qt.green)  
    label5.setPalette(palette) 
    label5.setAlignment( Qt.AlignLeft)
    #这里给文字说明增加特效（苏雨）
    label5.setStyleSheet(
    "QLabel:hover{color:green}"
    )
    
    label6.setText("Alitude:")
    label6.setAutoFillBackground(True) 
    palette = QPalette()        
    #palette.setColor(QPalette.Window,Qt.green)  
    label6.setPalette(palette) 
    label6.setAlignment( Qt.AlignLeft)    
    #这里给文字说明增加特效（苏雨）
    label6.setStyleSheet(
    "QLabel:hover{color:green}"
    )

    label7.setText("True airspeed:")
    label7.setAutoFillBackground(True) 
    palette = QPalette()        
    #palette.setColor(QPalette.Window,Qt.green)  
    label7.setPalette(palette) 
    label7.setAlignment( Qt.AlignLeft)
    #这里给文字说明增加特效（苏雨）
    label7.setStyleSheet(
    "QLabel:hover{color:green}"
    )

    label8.setText("Heading:")
    label8.setAutoFillBackground(True) 
    palette = QPalette()        
    #palette.setColor(QPalette.Window,Qt.green)  
    label8.setPalette(palette) 
    label8.setAlignment( Qt.AlignLeft)
    #这里给文字说明增加特效（苏雨）
    label8.setStyleSheet(
    "QLabel:hover{color:green}"
    )
    
    #定义打开Flightgear的按钮（苏雨）
    btn_1 = QPushButton(win)
    #设置窗口提示语（苏雨）
    btn_1.setToolTip("Open FlightGear!")
    #这里给按钮定义功能（苏雨）
    #首先创建AI飞机的xml文件（苏雨）
    btn_1.clicked.connect(FG_AI_create)
    btn_1.clicked.connect(FG_open)
    btn_1.clicked.connect(FG_protocol_create)    
        
    btn_1.setStyleSheet(
    #"QPushButton{color:yellow}"
    #"QPushButton{background:green}"
    #"QPushButton:hover{color:blue}"
    #"QPushButton:hover{background:red}" 
    #"QPushButton:pressed{color:pink}"
    #"QPushButton:pressed{background:brown}"
    #这里给按钮增加了背景图案和按键特效（苏雨）
    "QPushButton{border-image: url(/home/suyu/suyu/picture/open_background.png)}"
    "QPushButton:hover{border-image: url(/home/suyu/suyu/picture/open_hover.png)}"
    "QPushButton:pressed{border-image: url(/home/suyu/suyu/picture/open_pressed.png)}"
    )

    #icon=QIcon('FG_LOGO.png')
    
    #size=QSize(50,50)
    #btn_1.setIconSize(size)
    #btn_1.setIcon(QIcon("fglogosm.jpg"))
    #btn_1.setIcon(icon)
    #btn_1.setIconSize(size)
    #btn_1.resize(120,80)

    
    
    
    #定义连接Flightgear的按钮（苏雨）
    btn_2 = QPushButton(win)
    #设置窗口提示语（苏雨）
    btn_2.setToolTip("Connect to FlightGear!")
    btn_2.clicked.connect(FG_GPS_calibration)
    btn_2.clicked.connect(FG_connect)    
    btn_2.setStyleSheet(
    #这里给按钮增加了背景图案和按键特效（苏雨）
    "QPushButton{border-image: url(/home/suyu/suyu/picture/connect_background.png)}"
    "QPushButton:hover{border-image: url(/home/suyu/suyu/picture/connect_hover.png)}"
    "QPushButton:pressed{border-image: url(/home/suyu/suyu/picture/connect_pressed.png)}"
    )    
    
    #定义校准FG的飞机GPS定位的按钮（苏雨）
    btn_3 = QPushButton(win)
    btn_3.setToolTip('FlightGear GPS calibration!')    
    btn_3.clicked.connect(FG_GPS_calibration)
    btn_3.setStyleSheet(
    #这里给按钮增加了背景图案和按键特效（苏雨）
    "QPushButton{border-image: url(/home/suyu/suyu/picture/gps_background.png)}"
    "QPushButton:hover{border-image: url(/home/suyu/suyu/picture/gps_hover.png)}"
    "QPushButton:pressed{border-image: url(/home/suyu/suyu/picture/gps_pressed.png)}"
    ) 

    #定义数据分析仪器按钮（苏雨）
    btn_4 = QPushButton(win)
    btn_4.setToolTip('Data analyzer!')    
    #btn_4.clicked.connect(FG_GPS_calibration)
    btn_4.setStyleSheet(
    #这里给按钮增加了背景图案和按键特效（苏雨）
    "QPushButton{border-image: url(/home/suyu/suyu/picture/data_background.png)}"
    "QPushButton:hover{border-image: url(/home/suyu/suyu/picture/data_hover.png)}"
    "QPushButton:pressed{border-image: url(/home/suyu/suyu/picture/data_pressed.png)}"
    )

    #定义根据BS中飞机自动生成FG的AI飞机的xml文件的按钮，注意此按钮暂时不用，功能整合入第一个按钮！（苏雨）
    #btn_4 = QPushButton('Create AI aircrafts in FlightGear!')
    #btn_4.clicked.connect(FG_AI_create)
    


    #这里开始给窗口塞东西了！（苏雨）
    win.label1 = label1
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.label1.move(5,5)
    #第一个值是宽，第二个值是高（苏雨）
    label1.resize(210,18)

    win.echobox = echobox
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.echobox.move(5,25)
    #第一个值是宽，第二个值是高（苏雨）
    echobox.setFixedSize(500, 100)
    
    win.label2 = label2
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.label2.move(5,130)
    #第一个值是宽，第二个值是高（苏雨）
    label2.resize(210,18)    

    win.cmdline = cmdline
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.cmdline.move(5,150)
    #第一个值是宽，第二个值是高（苏雨）
    cmdline.setFixedSize(500, 100)
          
    win.btn_1 = btn_1
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.btn_1.move(5,260)
    #设置按钮的尺寸！（苏雨）
    btn_1.setFixedSize(120, 120)         

    win.btn_2 = btn_2
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.btn_2.move(130,260)
    #设置按钮的尺寸！（苏雨）
    btn_2.setFixedSize(120, 120) 

    win.btn_3 = btn_3
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.btn_3.move(255,260)
    #设置按钮的尺寸！（苏雨）
    btn_3.setFixedSize(120, 120) 

    win.btn_4 = btn_4
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.btn_4.move(380,260)
    #设置按钮的尺寸！（苏雨）
    btn_4.setFixedSize(120, 120)

    win.label3 = label3
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.label3.move(5,406)
    #第一个值是宽，第二个值是高（苏雨）
    label3.setFixedSize(190,18) 

    win.spinbox = spinbox
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.spinbox.move(325,400)
    #第一个值是宽，第二个值是高（苏雨）
    spinbox.setFixedSize(200,30)
    
    win.label4 = label4
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.label4.move(5,440)
    #第一个值是宽，第二个值是高（苏雨）
    label4.setFixedSize(220,18)    
    
    win.edita1 = edita1
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.edita1.move(225,440)
    #第一个值是宽，第二个值是高（苏雨）
    edita1.setFixedSize(300,18)    
    
    win.label5 = label5
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.label5.move(5,470)
    #第一个值是宽，第二个值是高（苏雨）
    label5.setFixedSize(220,18)

    win.edita2 = edita2
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.edita2.move(225,470)
    #第一个值是宽，第二个值是高（苏雨）
    edita2.setFixedSize(300,18)

    win.label6 = label6
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.label6.move(5,500)
    #第一个值是宽，第二个值是高（苏雨）
    label6.setFixedSize(220,18)

    win.edita3 = edita3
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.edita3.move(225,500)
    #第一个值是宽，第二个值是高（苏雨）
    edita3.setFixedSize(300,18)

    win.label7 = label7
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.label7.move(5,530)
    #第一个值是宽，第二个值是高（苏雨）
    label7.setFixedSize(220,18)    

    win.edita4 = edita4
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.edita4.move(225,530)
    #第一个值是宽，第二个值是高（苏雨）
    edita4.setFixedSize(300,18)

    win.label8 = label8
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.label8.move(5,560)
    #第一个值是宽，第二个值是高（苏雨）
    label8.setFixedSize(220,18)    

    win.edita5 = edita5
    #第一个值是水平方向，第二个值是垂直方向（苏雨）
    win.edita5.move(225,560)
    #第一个值是宽，第二个值是高（苏雨）
    edita5.setFixedSize(300,18)
          
    win.show()                      
    
    #先打开BlueSky再执行连接操作（苏雨） 
    BS_open()
    bsclient = TextClient()
    bsclient.connect(event_port=11000, stream_port=11001)
       
    # 这里才是主循环过程（苏雨）
    app.exec_()
#cre kl001 b737 37.329873 -121.815683 110 fl100 300    
